/*******************************************************************************
 * Copyright (c) 2011 EclipseDevX.org and others. All rights reserved. This program and the
 * accompanying materials are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at:
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package org.eclipsedevx.core;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipsedevx.core.usage.UsageStatsJob;
import org.eclipsedevx.core.workspace.WorkspaceListener;
import org.osgi.framework.BundleContext;

import java.util.UUID;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

/**
 * The activator class controls the plug-in life cycle.
 */
public class DevXCorePlugin extends AbstractUIPlugin {

  // The plug-in ID
  public static final String PLUGIN_ID = "org.eclipsedevx.core";

  // The shared instance
  private static DevXCorePlugin plugin;

  /**
   * Respects images residing in any plug-in. If path is relative, then this bundle is looked up for
   * the image, otherwise, for absolute path, first segment is taken as id of plug-in with image
   * 
   * @param path the path to image, either absolute (with plug-in id as first segment), or relative
   *          for bundled images
   * @return the image descriptor
   */
  public static ImageDescriptor findImageDescriptor(String path) {
    final IPath p = new Path(path);

    if (p.isAbsolute() && p.segmentCount() > 1) {
      return AbstractUIPlugin.imageDescriptorFromPlugin(p.segment(0),
          p.removeFirstSegments(1).makeAbsolute().toString());
    } else {
      return getBundledImageDescriptor(p.makeAbsolute().toString());
    }
  }

  /**
   * Returns an image descriptor for the image file at the given plug-in relative path.
   * 
   * @param path the path
   * @return the image descriptor
   */
  public static ImageDescriptor getBundledImageDescriptor(String path) {
    return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
  }

  /**
   * Get an image given a path relative to this plugin.
   * 
   * @param path
   * @return an image
   */
  public static Image getImage(String path) {
    if (getPlugin().getImageRegistry().get(path) != null) {
      return getPlugin().getImageRegistry().get(path);
    }

    ImageDescriptor descriptor = findImageDescriptor(path);

    if (descriptor != null) {
      getPlugin().getImageRegistry().put(path, descriptor);

      return getPlugin().getImageRegistry().get(path);
    }

    return null;
  }

  /**
   * Returns the shared instance
   * 
   * @return the shared instance
   */
  public static DevXCorePlugin getPlugin() {
    return plugin;
  }

  /**
   * Log the given exception to the Eclipse log.
   * 
   * @param t the exception to log
   */
  public static void logError(Throwable t) {
    getPlugin().getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, t.getMessage(), t));
  }

  private UsageStatsJob usageStatsJob;

  private ResourceManager resourceManager;

  private String MACHINE_ID;

  /**
   * The constructor
   */
  public DevXCorePlugin() {

  }

  public ResourceManager getImageManager() {
    if (resourceManager == null) {
      resourceManager = new LocalResourceManager(JFaceResources.getResources());
    }

    return resourceManager;
  }

  public String getMachineId() {
    if (MACHINE_ID == null) {
      MACHINE_ID = getMachineIdImpl();
    }

    return MACHINE_ID;
  }

  @Override
  public void start(BundleContext context) throws Exception {
    super.start(context);

    plugin = this;

    final long MILLIS_PER_MINUTE = 60 * 1000;

    usageStatsJob = new UsageStatsJob();
    usageStatsJob.schedule(30 * MILLIS_PER_MINUTE);

    WorkspaceListener.getInstance();
  }

  @Override
  public void stop(BundleContext context) throws Exception {
    plugin = null;

    super.stop(context);
  }

  private String generateMachineId() {
    UUID uuid = UUID.randomUUID();

    return Long.toHexString(uuid.getLeastSignificantBits()).toUpperCase();
  }

  private String getMachineIdImpl() {
    Preferences prefs = Preferences.userNodeForPackage(getClass());

    String id = prefs.get("machine.id", null);

    if (id == null) {
      id = generateMachineId();

      try {
        prefs.put("machine.id", id);
        prefs.flush();
      } catch (BackingStoreException bse) {
        DevXCorePlugin.logError(bse);
      }
    }

    return id;
  }

}
